﻿using Commons.Helpers;
using Commons.ReturnData;
using IdentityServer.Domain.Entities;
using IdentityServer.Domain.IRepositories;
using IdentityServer.Domain.IServices;
using IdentityServer.Infrastructure.Repositories;
using IdentityServer.Infrastructure.Services;
using IdentityServer.Infrastructure.Validators;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using System.Net;
using System.Security.Claims;

namespace IdentityServer.WebAPI.Controllers
{
    [Area("IdentityServer")]
    [Route("[area]/[controller]/[action]")]
    [ApiController]
    public class LoginController: ControllerBase
    {
        private readonly IIdRepository repository;
        private readonly IdDomainService idService;
        private readonly IEmailClient qqEmailClient;


        public Guid AppUserId { get; set; }

        public LoginController(IIdRepository repository, IdDomainService idService, IEmailClient qqEmailClient)
        {
            this.idService = idService;
            this.repository = repository;
            this.qqEmailClient = qqEmailClient;
        }

        [HttpPost]
        [AllowAnonymous]
        public async Task<ActionResult> CreateWorld()
        {
            if (await repository.FindByNameAsync("admin") != null)
            {
                return StatusCode((int)HttpStatusCode.Conflict, "已经初始化过了");
            }
            AppUser user = new AppUser("admin");
            var r = await repository.CreateAsync(user, "123456");
            Debug.Assert(r.Succeeded);
            var token = await repository.GenerateChangePhoneNumberTokenAsync(user, "18918999999");
            var cr = await repository.ChangePhoneNumAsync(user.Id, "18918999999", token);
            Debug.Assert(cr.Succeeded);
            r = await repository.AddToRoleAsync(user, "User");
            Debug.Assert(r.Succeeded);
            r = await repository.AddToRoleAsync(user, "Admin");
            Debug.Assert(r.Succeeded);
            return Ok();
        }
        [HttpPost]
        [AllowAnonymous]
        public async Task<MessageResult> EmailSendAsync(EmailRequest req)
        {
            if (req.email.EndsWith("@qq.com"))
            {

                return await idService.EmailSendAsync(req.email);
            }
            else
            {
                return new MessageResult(400, "请用QQ邮箱注册", false);
            }
        }



        [HttpPost]
        [AllowAnonymous]
        public async Task<MessageResult> CreateByEmailAsync(RegisterUserByEmailAndPwdRequest req)
        {
            var codeCheck = await qqEmailClient.EmailRepository.FindEmailSenderAsync(req.Email, req.Code);
            if (codeCheck)
            {
                var res = await idService.CreateByEmailAsync(req.UserName, req.Email, req.Password1);
                Debug.Assert(res.Succeeded);
                return new MessageResult("账号创建成功");
            }
            else
            {
                return new MessageResult(404,"验证码错误",false);
            }

        }

        [HttpGet]
        [Authorize]
        public async Task<ActionResult<UserResponse>> GetUserInfo()
        {
            string userId = this.User.FindFirstValue(ClaimTypes.NameIdentifier);
            var user = await repository.FindByIdAsync(Guid.Parse(userId));
            if (user == null)//可能用户注销了
            {
                return NotFound();
            }
            //出于安全考虑，不要机密信息传递到客户端
            //除非确认没问题，否则尽量不要直接把实体类对象返回给前端
            return new UserResponse(user.Id, user.PhoneNumber, user.CreationTime);
        }
        [AllowAnonymous]
        [HttpPost]
        public async Task<ActionResult<string?>> LoginByPhoneAndPwd(LoginByPhoneAndPwdRequest req)
        {
            //todo：要通过行为验证码、图形验证码等形式来防止暴力破解
            (var checkResult, string? token) = await idService.LoginByPhoneAndPwdAsync(req.PhoneNumber, req.Password);
            if (checkResult.Succeeded)
            {
                return token;
            }
            else if (checkResult.IsLockedOut)
            {
                //尝试登录次数太多
                return StatusCode((int)HttpStatusCode.Locked, "此账号已经锁定");
            }
            else
            {
                string msg = "登录失败";
                return StatusCode((int)HttpStatusCode.BadRequest, msg);
            }
        }

        [AllowAnonymous]
        [HttpPost]
        public async Task<ActionResult<string>> LoginByUserNameAndPwd(
            LoginByUserNameAndPwdRequest req)
        {
            (var checkResult, var token) = await idService.LoginByUserNameAndPwdAsync(req.UserName, req.Password);
            if (checkResult.Succeeded) return token!;
            else if (checkResult.IsLockedOut)//尝试登录次数太多
                return StatusCode((int)HttpStatusCode.Locked, "用户已经被锁定");
            else
            {
                string msg = checkResult.ToString();
                return BadRequest("登录失败" + msg);
            }
        }
        /// <summary>
        /// 用户名或者邮箱登录
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost]
        public async Task<LoginResult> LoginByEmailAndPwd(
            LoginByEmailAndPwdRequest req)
        {
            var checkResult = new Microsoft.AspNetCore.Identity.SignInResult();
            string token = "";
            if (req.Email.Contains("@"))
            {
                if (req.Email.Contains("qq.com"))
                {
                    (checkResult, token) = await idService.LoginByEmailAndPwdAsync(req.Email, req.Password);
                    
                }
                else
                {
                    return new LoginResult(400, "请用QQ邮箱或用户名登录");
                }
                    
            }
            else
            {
                (checkResult, token) = await idService.LoginByUserNameAndPwdAsync(req.Email, req.Password);
            }
            if (checkResult.Succeeded) return new LoginResult(token!);
            else if (checkResult.IsLockedOut)//尝试登录次数太多
                return new LoginResult((int)HttpStatusCode.Locked, "用户已经被锁定");
            else
            {
                string msg = checkResult.ToString();
                return new LoginResult(400, "账号或者密码错误");
            }

        }

        [HttpPost]
        [Authorize]
        public async Task<ActionResult> ChangeMyPassword(ChangeMyPasswordRequest req)
        {
            Guid userId = Guid.Parse(this.User.FindFirstValue(ClaimTypes.NameIdentifier));
            var resetPwdResult = await repository.ChangePasswordAsync(userId, req.Password);
            if (resetPwdResult.Succeeded)
            {
                return Ok();
            }
            else
            {
                return BadRequest(resetPwdResult.Errors.SumErrors());
            }
        }

        [HttpGet]
        [AllowAnonymous]
        public async Task<LoginResult>  LoginByWeChatAsync(string code)
        {
            return await idService.loginByWeChatOpenIdAsync(code);
        }
    }
}
